package org.naxx.security.datatype.impl;

import java.io.FileInputStream;
import java.io.InputStream;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;

import org.naxx.security.datatype.DataType;
import org.naxx.security.datatype.DataTypeDefinitionLoader;
import org.naxx.security.parser.datatype.DataTypeParser;
import org.naxx.security.util.FileSystemUtil;

/**
 * XML based implementation of parent interface API which loads
 * type definitions from <code>resources/datatype/datatypes.xml</code>.
 */
public final class DataTypeDefinitionLoaderImpl implements DataTypeDefinitionLoader {
	
	private DataTypeParser dataTypeParser;
	
	public void setDataTypeParser(DataTypeParser dataTypeParser) {
		this.dataTypeParser = dataTypeParser;
	}

	public Set<DataType> loadDataTypeDefinitions() {
		InputStream in = null;
		XMLEventReader reader = null;
		try {
			in = new FileInputStream("resources/datatype/datatypes.xml");
			reader = XMLInputFactory.newInstance().createXMLEventReader(in);
			this.dataTypeParser.skipDocumentStart(reader);
			reader.nextTag();
			List<DataType> dataTypesList = dataTypeParser.parse(reader);
			
			Set<DataType> dataTypesSet = new HashSet<DataType>(dataTypesList.size());
			for(DataType dataType : dataTypesList) {
				if(dataTypesSet.contains(dataType)) {
					throw new IllegalStateException("Data type definitions loaded from" +
						" external source have two types with same id/uri : " + dataType);
				}
				dataTypesSet.add(dataType);
			}
			
			return dataTypesSet;
		} catch (Exception e) {
			throw new IllegalStateException("Unable to load data types definitions!", e);
		}
		finally {
			FileSystemUtil.release(reader);
			FileSystemUtil.close(in);
		}
	}
}
